import { filter } from 'lodash-es';

interface EnumObject<L = number | string, T = any> {
  value: T;
  label?: L;
}
interface EnumBase<L = number | string, T = any> extends EnumObject<L, T> {
  key: number | string;
  label: L;
}
type Keys<E> = keyof E;
type EnumItemType = EnumObject | number | string | boolean | symbol;
type EnumType<E extends Record<number | string, EnumItemType>> = {
  [K in Keys<E>]: E[K] extends EnumObject ? E[K]['value'] : E[K];
};

export type Unionize<T extends EnumType<any>> = {
  [P in keyof T]: { [Q in T[P]]: P };
}[keyof T];
export type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
  k: infer I
) => void
  ? I
  : never;

export type EnumValueType<E> = Keys<UnionToIntersection<Unionize<E>>>;

export const Enum = <E extends Record<number | string, EnumItemType>>(enumSourceData: E) => {
  // 根据数据源处理返回枚举类型

  const enumArr: EnumBase<keyof E, any>[] = [];
  const enums: EnumType<E> = {} as EnumType<E>;
  const entries = Object.entries(enumSourceData);
  entries.forEach(([key, values]) => {
    if (typeof values === 'object') {
      const { value, label } = values;
      enumArr.push({ key, value, label: label ?? key });
      enums[key as keyof E] = value;
    } else {
      enumArr.push({ key, value: values, label: key });
      enums[key as keyof E] = values as any;
    }
  });
  type M = UnionToIntersection<Unionize<EnumType<E>>>;
  return {
    list: enumArr,
    enum: enums,
    /**
     * 根据枚举值获取相应的 label
     * @param {any} value 需要查询的枚举值
     * @returns {string} 对应的label
     */
    getLabelByValue<V extends Keys<M>>(value: V): typeof value extends V ? M[V] : '' {
      const filterObject = filter(enumArr, (item) => item.value === value);

      // 存在返回值，返回第一个匹配的数据
      if (filterObject.length > 0) {
        return filterObject[0].label as any;
      }

      // 没有返回值的情况下，返回空
      return '' as any;
    }
  };
};
